#!/usr/bin/python
# -*- coding: utf-8 -*-

from PyQt4.QtGui import *
from PyQt4.QtCore import *
#from PyQt4 import QtGui
from cLocation import cLocation

class cHistory():
    def __init__(self, statstr, parent, loc):
        self.statstr = statstr
        self.parent = parent
        self.loc = loc
    def IsIn(self, otherList):
        for elem in otherList:
            if self.statstr == elem.statstr:
                return True
        return False

class cWideSearch(QThread):
    def __init__(self, parent=None):
        super(cWideSearch, self).__init__(parent)
        self.stoped = False
        self.mutex = QMutex()
 
    def run(self):
        with QMutexLocker(self.mutex):
            self.stoped = False
        while not self.stoped:
            self.WideSearch(self.Father)
            self.Father.Now += 1
            self.emit(SIGNAL("updateTime()"))
 
    def stop(self):
        with QMutexLocker(self.mutex):
            self.stoped = True
 
    def isStoped(self):    
        with QMutexLocker(sellf.mutex):
            return self.stoped    
            
    def WideSearch(self_me, self):
        #print("enter", self.HistoryArray, self.Now)
        # See if searched all
        if self.Now >= len(self.HistoryArray):
            self_me.stoped = True
            self_me.emit(SIGNAL("mbox()"))
            return
                           
        statstr = self.HistoryArray[self.Now].statstr
        stat = self.Str2List(statstr)
        # See if meeted
        Dis = int(statstr[self.RowColumn:])
        #Dis = self.FindSimilarity(stat)
        if Dis == 0:
            #mbox = QtGui.QMessageBox()
            #mbox.setText("Find solution.")
            #mbox.exec_()
            self.Found = True
            self_me.stoped = True
            self_me.emit(SIGNAL("mbox()"))
            return
        # Find the location of person and Boxes
        LocBoxes = []
        for i in range(self.Rows):
            for j in range(self.Columns):
                if stat[i][j] & self.Person:
                    LocPerson = cLocation(i, j)
                elif stat[i][j] & self.Box:
                    LocBoxes.append(cLocation(i, j))
        # Find all the places that person can go
        can_go = self.CheckConnecty(stat)
        FromDirectionList = [cLocation(0, 1), cLocation(0, -1), \
                             cLocation(1, 0), cLocation(-1, 0)]
        # Find the later situations
        for LocBox, FromLoc in [(xx, yy) for xx in LocBoxes \
                                         for yy in FromDirectionList]:
            PushLoc = LocBox.Move(FromLoc)
            if PushLoc.IfOut(self.Rows, self.Columns):
                continue
            if not can_go[PushLoc.x][PushLoc.y]:
                continue
            newLocBox = LocBox.MoveInv(FromLoc)
            # see if the Box can move there
            if newLocBox.IfOut(self.Rows, self.Columns):
                continue
            if self.Dead[newLocBox.x][newLocBox.y]:
                continue
            if stat[newLocBox.x][newLocBox.y] & self.Wall or \
               stat[newLocBox.x][newLocBox.y] & self.Box:
                continue
            # copy a new stat
            newstat = []
            for i in range(self.Rows):
                tmp = []
                for j in range(self.Columns):
                    tmp.append(stat[i][j])
                newstat.append(tmp)
            # move the box
            newstat[LocBox.x][LocBox.y] -= self.Box
            newstat[newLocBox.x][newLocBox.y] += self.Box
            # move the person
            newstat[LocPerson.x][LocPerson.y] -= self.Person
            newstat[LocBox.x][LocBox.y] += self.Person
            if self.FindDynamicDeadPoint(newstat):
                continue
            # generate the new status
            newstr = self.List2Str(newstat)
            newNode = cHistory(newstr, self.Now, FromLoc)
            newDis = int(newstr[self.RowColumn:])
            if newNode.IsIn(self.HistoryArray):
                continue
            # find the location of insert
            i = self.Now + 1
            while i < len(self.HistoryArray):
                tDis = int(self.HistoryArray[i].statstr[self.RowColumn:])
                if tDis > newDis:
                    break
                i += 1
            # insert
            self.HistoryArray.insert(i, newNode)
            #self.HistoryArray.append(newNode)
        #print("exit", self.History, self.Now)
